package com.usb.serial.device;

import android.util.Log;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;

import static java.lang.Thread.interrupted;

public abstract class SerialHelper {
    private SerialPort mSerialPort;
    private OutputStream mOutputStream;
    private InputStream mInputStream;
    private ReadThread mReadThread;
    private String sPort = "/dev/ttyS4";
    private int iBaudRate = 115200;
    private boolean _isOpen = false;
    private byte[] _bLoopData = new byte[]{0x30};
    private int iDelay = 500;
    String TAG = this.getClass().getSimpleName();

    public SerialHelper(String sPort, int iBaudRate) {
        this.sPort = sPort;
        this.iBaudRate = iBaudRate;
    }

    public SerialHelper() {
        this("/dev/ttyS4", 115200);
    }

    public SerialHelper(String sPort) {
        this(sPort, 115200);
    }

    public SerialHelper(String sPort, String sBaudRate) {
        this(sPort, Integer.parseInt(sBaudRate));
    }


    public void open() throws IOException {
        mSerialPort = new SerialPort(new File(sPort), iBaudRate, 0);

        mInputStream = mSerialPort.getInputStream();// new FileInputStream() ;
        mOutputStream = mSerialPort.getOutputStream();

        mReadThread = new ReadThread();
        mReadThread.start();
        _isOpen = true;

    }

    public boolean isOpen() {
        return _isOpen;
    }

    public void sendTxt(String sTxt) {
        byte[] bOutArray = sTxt.getBytes();
        send(bOutArray);
    }


    public void send(byte[] bOutArray) {
        try {
            mOutputStream.write(bOutArray);
//          mOutputStream.flush();
            byte[] b = new byte[]{00, 05, 00, 05, 00, 00};
            //0x00, 0x05, 0x00, 0x05, 0x00, 0x00
            //00 05 00 05 00 00
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {

                        if (mInputStream != null) {
                            int available = mInputStream.available();
                            if (mInputStream == null) return;
                            byte[] buffer = new byte[512];
//                    Log.i(TAG, "run: read ");
                            int size = mInputStream.read(buffer);
                            Log.i(TAG, "size: " + size);
                            if (size > 0) {
                                byte[] bytes1 = new byte[size];
                                System.arraycopy(buffer, 0, bytes1, 0, size);
                                ComBean ComRecData = new ComBean(sPort, bytes1, size);
                                onDataReceived(ComRecData);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static public String Byte2Hex(Byte inByte) {
        return String.format("%02x", inByte).toUpperCase();
    }

    static public String CreditcardByteArrToHex(byte[] inBytArr, int size) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(512);
        byteBuffer.put(inBytArr);

        StringBuilder strBuilder = new StringBuilder();
        int j = inBytArr.length;
        for (int i = 0; i < size; i++) {
            strBuilder.append(Byte2Hex(inBytArr[i]));
            strBuilder.append(" ");
        }
        return strBuilder.toString();
    }

    class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                try {
                    int available = mInputStream.available();
                    if (mInputStream == null) return;
                    byte[] buffer = new byte[512];
//                    Log.i(TAG, "run: read ");
                    int size = mInputStream.read(buffer);
                    Log.i(TAG, "size: " + size);
                    if (size > 0) {
                        byte[] bytes1 = new byte[size];
                        System.arraycopy(buffer, 0, bytes1, 0, size);
                        ComBean ComRecData = new ComBean(sPort, bytes1, size);
                        onDataReceived(ComRecData);
                    }
                    try {
                        Thread.sleep(50);//延时50ms
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

    protected abstract void onDataReceived(ComBean comBean);


    class ComBean {
        public byte[] bRec = null;
        public String sRecTime = "";
        public String sComPort = "";

        String sPort;
        byte[] bytes;
        int size;

        public ComBean(String sPort, byte[] bytes, int size) {
            this.sPort = sPort;
            this.bytes = bytes;
            this.size = size;
            bRec = new byte[size];
            for (int i = 0; i < size; i++) {
                bRec[i] = bytes[i];
            }
            SimpleDateFormat sDateFormat = new SimpleDateFormat("hh:mm:ss");
            sRecTime = sDateFormat.format(new java.util.Date());
        }

    }

    public int getBaudRate() {
        return iBaudRate;
    }

    public boolean setBaudRate(int iBaud) {
        if (_isOpen) {
            return false;
        } else {
            iBaudRate = iBaud;
            return true;
        }
    }

    public boolean setBaudRate(String sBaud) {
        int iBaud = Integer.parseInt(sBaud);
        return setBaudRate(iBaud);
    }

    //----------------------------------------------------
    public String getPort() {
        return sPort;
    }

    public boolean setPort(String sPort) {
        if (_isOpen) {
            return false;
        } else {
            this.sPort = sPort;
            return true;
        }
    }

    //   protected   abstract void send(byte[] getbLoopData);

    protected byte[] getbLoopData() {
        return _bLoopData;
    }

    protected byte[] setbLoopData(byte[] mloopData) {
        return _bLoopData;
    }

    public void close() {
        if (mReadThread != null)
            mReadThread.interrupt();
        if (mSerialPort != null) {
            mSerialPort.close();
            mSerialPort = null;
        }
        _isOpen = false;
    }

}
